package com.witmore.skyline.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.witmore.skyline.db.entity.*;
import com.witmore.skyline.db.mapper.*;
import com.witmore.skyline.db.mapper.dto.ProjectDeviceDetailDTO;
import com.witmore.skyline.db.mapper.dto.ProjectDeviceWorkDaysDTO;
import com.witmore.skyline.web.config.BusinessConfig;
import com.witmore.skyline.web.config.GlobalAccountSession;
import com.witmore.skyline.web.controller.enums.WitmoreErrorCode;
import com.witmore.skyline.web.controller.enums.WorkStatusEnum;
import com.witmore.skyline.web.controller.vo.param.*;
import com.witmore.skyline.web.controller.vo.result.*;
import com.witmore.skyline.web.service.CameraService;
import com.witmore.skyline.web.service.ProjectService;
import com.witmore.skyline.web.utils.AddressParserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.witmore.skyline.web.utils.AddressParserUtils.parseAddress;

/**
 * Description: ProjectServiceImpl
 * Author: 豆子高
 * Date: 2025/2/27 10:19
 */
@Slf4j
@Service
public class ProjectServiceImpl implements ProjectService {


    @Autowired
    private OrgMapper orgMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceDailyReportMapper deviceDailyReportMapper;
    @Autowired
    private CameraMapper cameraMapper;
    @Autowired
    private ProjectBusinessRefMapper projectBusinessRefMapper;
    @Autowired
    private CameraService cameraService;
    @Autowired
    private BusinessConfig businessConfig;

    @Override
    public List<Integer> getProjectIdsWithChildren(Integer projectId) {
        List<Integer> result = new ArrayList<>();
        // 添加当前项目id
        result.add(projectId);
        // 递归查询子项目
        this.findChildrenIds(projectId, result);
        return result;
    }

    @Override
    public ResponseResult<List<ProjectResultVO>> getProjectTree(Integer orgId) {
        return this.getProjectTree(orgId, false);
    }

    @Override
    public ResponseResult<List<ProjectResultVO>> getProjectTree(Integer orgId, Boolean needCamera) {
        return this.getProjectTree(orgId, needCamera, false);
    }

    @Override
    public ResponseResult<List<ProjectResultVO>> getProjectTree(Integer orgId, Boolean needCamera, Boolean needCameraPic) {
        // 查询所有的项目
        List<ProjectDO> projectList = projectMapper.selectList(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getOrgId, orgId)
                .eq(ProjectDO::getIsDeleted, 0));
        if (projectList.isEmpty()) {
            return ResponseResult.success(new ArrayList<>());
        }
        // 拷贝List<ProjectDO>到List<ProjectTreeVO>
        List<ProjectResultVO> projectResultVOS = new ArrayList<>();
        for (ProjectDO projectDO : projectList) {
            ProjectResultVO projectResultVO = new ProjectResultVO();
            BeanUtils.copyProperties(projectDO, projectResultVO);
            projectResultVOS.add(projectResultVO);
        }
        // 拼接企业信息
        OrgDO orgDO = orgMapper.selectById(orgId);
        ProjectResultVO resultVO = new ProjectResultVO();
        resultVO.setId(0);
        resultVO.setProjectName(orgDO.getOrgName());
        // 构建树形结构
        long startTime = System.currentTimeMillis();
        resultVO.setChildren(this.buildTree(projectResultVOS, orgId, needCamera, needCameraPic));
        System.out.println("构建树形结构耗时：" + (System.currentTimeMillis() - startTime) + "ms");
        resultVO.setOrgId(orgId);
        resultVO.setProjectLevel(0);
        resultVO.setParentId(-1);
        return ResponseResult.success(Collections.singletonList(resultVO));
    }


    @Override
    public String getProjectNamesPathByProjectId(Integer projectId) {
        StringBuilder path = new StringBuilder();
        int currentId = projectId;
        while (true) {
            // 查询当前项目
            ProjectDO project = projectMapper.selectById(currentId);
            if (project == null) {
                break; // 项目不存在，退出循环
            }
            // 拼接路径
            if (path.length() > 0) {
                path.insert(0, "/"); // 只有在路径不为空时才添加 "/"
            }
            path.insert(0, project.getProjectName());
            // 如果当前项目是根项目，退出循环
            if (project.getParentId() == 0) {
                break;
            }

            // 继续查询父项目
            currentId = project.getParentId();
        }
        return path.toString();
    }

    @Override
    public ResponsePageResult<ProjectResultVO> projectListPage(ProjectParamVO projectParamVO) {
        Page<ProjectDO> projectDOPage = projectMapper.selectPage(new Page<>(projectParamVO.getPage(), projectParamVO.getSize()),
                new LambdaQueryWrapper<ProjectDO>()
                        .like(!ObjectUtils.isEmpty(projectParamVO.getProjectName()), ProjectDO::getProjectName, projectParamVO.getProjectName())
                        .eq(!ObjectUtils.isEmpty(projectParamVO.getCity()), ProjectDO::getCity, projectParamVO.getCity())
                        .eq(ProjectDO::getOrgId, projectParamVO.getOrgId())
                        .eq(ProjectDO::getIsDeleted, 0)
        );
        if (projectDOPage == null) {
            return ResponsePageResult.fail(WitmoreErrorCode.SYSTEM_ERROR);
        }
        return ResponsePageResult.success(projectDOPage, (projectDO) -> {
            ProjectResultVO projectResultVO = new ProjectResultVO();
            BeanUtils.copyProperties(projectDO, projectResultVO);
            projectResultVO.setProjectNames(this.getProjectNamesPathByProjectId(projectDO.getId()));
            projectResultVO.setDeviceTotal(0);
            projectResultVO.setCameraTotal(0);
            // 设备数量
            List<Integer> deviceIdListByProjectId = this.getBusinessIdListByProjectId(projectDO.getOrgId(), projectDO.getId(), 1);
            if (CollectionUtils.isNotEmpty(deviceIdListByProjectId)) {
                projectResultVO.setDeviceTotal(deviceIdListByProjectId.size());
            }
            // 摄像头总数
            List<Integer> cameraIdListByProjectId = this.getBusinessIdListByProjectId(projectDO.getOrgId(), projectDO.getId(), 2);
            if (CollectionUtils.isNotEmpty(cameraIdListByProjectId)) {
                projectResultVO.setCameraTotal(cameraIdListByProjectId.size());
            }
            return projectResultVO;
        });
    }


    @Override
    public ResponseResult<HomeStatisticsVO> getHomeStatistics(AccountSession accountSession) {
        // 企业名下设备总数
        Long deviceCount = deviceMapper.selectCount(new LambdaQueryWrapper<DeviceDO>()
                .eq(DeviceDO::getOrgId, accountSession.getOrgId())
                .eq(DeviceDO::getIsDeleted, 0));
        // 企业名下在线设备数（怠速+在线+负荷）
        Long deviceOnlineTotal = deviceMapper.selectCount(new LambdaQueryWrapper<DeviceDO>()
                .eq(DeviceDO::getOrgId, accountSession.getOrgId())
                .in(DeviceDO::getWorkStatus, WorkStatusEnum.IDLE.getCode(), WorkStatusEnum.ONLINE.getCode(), WorkStatusEnum.LOAD.getCode())
                .eq(DeviceDO::getIsDeleted, 0));
        // 企业名下负荷设备数（负荷状态）
        Long deviceLoadTotal = deviceMapper.selectCount(new LambdaQueryWrapper<DeviceDO>()
                .eq(DeviceDO::getOrgId, accountSession.getOrgId())
                .in(DeviceDO::getWorkStatus, WorkStatusEnum.LOAD.getCode())
                .eq(DeviceDO::getIsDeleted, 0));
        // 企业名下怠速设备数（在线+怠速状态）
        Long deviceIdlTotal = deviceMapper.selectCount(new LambdaQueryWrapper<DeviceDO>()
                .eq(DeviceDO::getOrgId, accountSession.getOrgId())
                .in(DeviceDO::getWorkStatus, WorkStatusEnum.IDLE.getCode(), WorkStatusEnum.ONLINE.getCode())
                .eq(DeviceDO::getIsDeleted, 0));
        // 企业名下负荷工作时长超过阈值的设备数（今日施工设备）
        int deviceLoadWorkingTotal = deviceMapper.selectLoadWorkingCount(accountSession.getOrgId(), null, businessConfig.getLoadWorkTimeThreshold());
        // 企业名下负荷工作时长小于阈值的设备数（今日未施工设备）
        int deviceUnWorkingTotal = deviceMapper.selectUnWorkingCount(accountSession.getOrgId(), null, businessConfig.getLoadWorkTimeThreshold());
        // 企业名下视频总数
        Long cameraTotal = cameraMapper.selectCount(new LambdaQueryWrapper<CameraDO>()
                .eq(CameraDO::getOrgId, accountSession.getOrgId())
                .eq(CameraDO::getIsDeleted, 0));
        // 企业名下在线视频数
        Long cameraOnlineTotal = cameraMapper.selectCount(new LambdaQueryWrapper<CameraDO>()
                .eq(CameraDO::getOrgId, accountSession.getOrgId())
                .eq(CameraDO::getCameraStatus, 1)
                .eq(CameraDO::getIsDeleted, 0));
        // 企业名下项目部总数
        Long projectTotal = projectMapper.selectCount(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getOrgId, accountSession.getOrgId())
                .eq(ProjectDO::getIsDeleted, 0));
        // 企业名下今日有施工设备的项目数
        int projectWorkingTotal = deviceMapper.selectWorkingProjectCount(accountSession.getOrgId(), null, null, null, businessConfig.getLoadWorkTimeThreshold());
        return ResponseResult.success(HomeStatisticsVO.builder()
                .deviceTotal(null == deviceCount ? 0 : deviceCount.intValue())
                .deviceOnlineTotal(null == deviceOnlineTotal ? 0 : deviceOnlineTotal.intValue())
                .deviceLoadTotal(null == deviceLoadTotal ? 0 : deviceLoadTotal.intValue())
                .deviceIdlTotal(null == deviceIdlTotal ? 0 : deviceIdlTotal.intValue())
                .deviceLoadWorkingTotal(deviceLoadWorkingTotal)
                .deviceUnWorkingTotal(deviceUnWorkingTotal)
                .cameraTotal(null == cameraTotal ? 0 : cameraTotal.intValue())
                .cameraOnlineTotal(null == cameraOnlineTotal ? 0 : cameraOnlineTotal.intValue())
                .projectTotal(null == projectTotal ? 0 : projectTotal.intValue())
                .projectWorkingTotal(projectWorkingTotal)
                .build());
    }






    @Override
    public List<Integer> getBusinessIdList(Integer orgId, List<Integer> projectIdsWithChildren, Integer type) {
        if (org.springframework.util.CollectionUtils.isEmpty(projectIdsWithChildren)) {
            return new ArrayList<>();
        }

        // 如果是摄像头类型(type=2)，直接从camera表查询
        if (type == 2) {
            List<CameraDO> cameraDOS = cameraMapper.selectList(new LambdaQueryWrapper<CameraDO>()
                    .in(CameraDO::getProjectId, projectIdsWithChildren)
                    .eq(CameraDO::getOrgId, orgId)
                    .eq(CameraDO::getIsDeleted, 0));
            return cameraDOS.stream()
                    .map(CameraDO::getId)
                    .collect(Collectors.toList());
        }

        // 如果是设备类型(type=1)，直接从device表查询
        if (type == 1) {
            List<DeviceDO> deviceDOS = deviceMapper.selectList(new LambdaQueryWrapper<DeviceDO>()
                    .in(DeviceDO::getProjectId, projectIdsWithChildren)
                    .eq(DeviceDO::getOrgId, orgId)
                    .eq(DeviceDO::getIsDeleted, 0));
            return deviceDOS.stream()
                    .map(DeviceDO::getId)
                    .collect(Collectors.toList());
        }

        // 其他类型(管理员)仍然使用关联表查询
        List<ProjectBusinessRefDO> projectBusinessRefDOS = projectBusinessRefMapper.selectList(new QueryWrapper<ProjectBusinessRefDO>()
                .in("project_id", projectIdsWithChildren)
                .eq("org_id", orgId)
                .eq("type", type));
        if (org.springframework.util.CollectionUtils.isEmpty(projectBusinessRefDOS)) {
            return new ArrayList<>();
        }
        return projectBusinessRefDOS.stream()
                .map(ProjectBusinessRefDO::getSkylineBusinessId)
                .collect(Collectors.toList());
    }

    @Override
    public List<Integer> getBusinessIdListByProjectId(Integer orgId, Integer projectId, Integer type) {
        if (projectId == null) {
            return Collections.emptyList();
        }
        // 首先查询 当前项目id下的子项目列表
        List<Integer> projectIdsWithChildren = this.getProjectIdsWithChildren(projectId);
        // 查询当前项目列表下的 业务id列表
        List<Integer> businessIdList = this.getBusinessIdList(orgId, projectIdsWithChildren, type);
        if (org.springframework.util.CollectionUtils.isEmpty(businessIdList)) {
            return Collections.emptyList();
        }
        return businessIdList;
    }

    @Override
    public String getProjectNameByBusinessId(Integer businessId, Integer type) {
        // 如果是摄像头类型(type=2)，直接从camera表查询项目信息
        if (type == 2) {
            CameraDO cameraDO = cameraMapper.selectOne(new LambdaQueryWrapper<CameraDO>()
                    .eq(CameraDO::getId, businessId)
                    .eq(CameraDO::getIsDeleted, 0));
            if (cameraDO == null || cameraDO.getProjectId() == null) {
                return "";
            }
            ProjectDO projectDO = projectMapper.selectById(cameraDO.getProjectId());
            return projectDO == null ? "" : projectDO.getProjectName();
        }

        // 其他类型(设备、管理员)仍然使用关联表查询
        List<ProjectBusinessRefDO> projectBusinessRefDO = projectBusinessRefMapper.selectList(new LambdaQueryWrapper<ProjectBusinessRefDO>()
                .eq(ProjectBusinessRefDO::getSkylineBusinessId, businessId)
                .eq(ProjectBusinessRefDO::getType, type)
        );
        if (CollectionUtils.isEmpty(projectBusinessRefDO)) {
            return "";
        }
        // 正常情况下只会有一条数据 默认取一条
        ProjectBusinessRefDO project = projectBusinessRefDO.get(0);
        ProjectDO projectDO = projectMapper.selectById(project.getProjectId());
        return projectDO == null ? "" : projectDO.getProjectName();
    }

    @Override
    public Integer getProjectIdByBusinessId(Integer businessId, Integer type) {
        // 如果是摄像头类型(type=2)，直接从camera表查询项目ID
        if (type == 2) {
            CameraDO cameraDO = cameraMapper.selectOne(new LambdaQueryWrapper<CameraDO>()
                    .eq(CameraDO::getId, businessId)
                    .eq(CameraDO::getIsDeleted, 0));
            return cameraDO != null ? cameraDO.getProjectId() : null;
        }

        // 如果是设备类型(type=1)，直接从device表查询项目ID
        if (type == 1) {
            DeviceDO deviceDO = deviceMapper.selectOne(new LambdaQueryWrapper<DeviceDO>()
                    .eq(DeviceDO::getId, businessId)
                    .eq(DeviceDO::getIsDeleted, 0));
            return deviceDO != null ? deviceDO.getProjectId() : null;
        }

        // 其他类型(管理员)使用关联表查询
        ProjectBusinessRefDO projectBusinessRefDO = projectBusinessRefMapper.selectOne(new LambdaQueryWrapper<ProjectBusinessRefDO>()
                .eq(ProjectBusinessRefDO::getSkylineBusinessId, businessId)
                .eq(ProjectBusinessRefDO::getType, type)
        );
        return projectBusinessRefDO != null ? projectBusinessRefDO.getProjectId() : null;
    }

    @Override
    public List<ProjectDO> getProjectParentListByBusinessId(Integer businessId, Integer type) {
        Integer projectId = null;

        // 如果是摄像头类型(type=2)，直接从camera表查询项目ID
        if (type == 2) {
            CameraDO cameraDO = cameraMapper.selectOne(new LambdaQueryWrapper<CameraDO>()
                    .eq(CameraDO::getId, businessId)
                    .eq(CameraDO::getIsDeleted, 0));
            projectId = cameraDO != null ? cameraDO.getProjectId() : null;
        }
        // 如果是设备类型(type=1)，直接从device表查询项目ID
        else if (type == 1) {
            DeviceDO deviceDO = deviceMapper.selectOne(new LambdaQueryWrapper<DeviceDO>()
                    .eq(DeviceDO::getId, businessId)
                    .eq(DeviceDO::getIsDeleted, 0));
            projectId = deviceDO != null ? deviceDO.getProjectId() : null;
        }
        // 其他类型(管理员)使用关联表查询
        else {
            List<ProjectBusinessRefDO> projectBusinessRefDO = projectBusinessRefMapper.selectList(new LambdaQueryWrapper<ProjectBusinessRefDO>()
                    .eq(ProjectBusinessRefDO::getSkylineBusinessId, businessId)
                    .eq(ProjectBusinessRefDO::getType, type)
                    .eq(ProjectBusinessRefDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
            );
            if (CollectionUtils.isNotEmpty(projectBusinessRefDO)) {
                ProjectBusinessRefDO projectBusinessRef = projectBusinessRefDO.get(0);
                projectId = projectBusinessRef.getProjectId();
            }
        }

        if (projectId == null) {
            return List.of();
        }

        List<ProjectDO> parentProjects = new ArrayList<>();
        ProjectDO projectDO = projectMapper.selectById(projectId);
        // 从当前节点开始，向上遍历直到根节点
        while (projectDO != null) {
            // 将当前节点名称添加到列表的开头
            parentProjects.add(0, projectDO);
            Integer parentId = projectDO.getParentId();
            // 根据你的定义，根节点的parentId为0或null
            if (parentId == null || parentId == 0) {
                break;
            }
            projectDO = projectMapper.selectById(parentId);
        }
        // 拼接顶级企业信息
        OrgDO orgDO = orgMapper.selectById(GlobalAccountSession.getUserInfo().getOrgId());
        ProjectDO parentProject = ProjectDO.builder()
                .id(0)
                .projectName(orgDO.getOrgName())
                .parentId(-1)
                .build();
        parentProjects.add(0, parentProject);
        return parentProjects;
    }

    @Override
    public ResponseResult<Void> add(ProjectAddParam param) {
        // 项目部名称唯一性校验
        ProjectDO projectDO = projectMapper.selectOne(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getProjectName, param.getProjectName())
                .eq(ProjectDO::getIsDeleted, 0)
                .eq(ProjectDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
        );
        if (projectDO != null) {
            return ResponseResult.fail(WitmoreErrorCode.PROJECT_NAME_EXIST);
        }
        int level = 1;
        Integer parentId = param.getParentId();
        if (parentId == null) {
            parentId = 0;
        }
        // 校验父项目是否存在
        if (parentId > 0) {
            ProjectDO parentProject = projectMapper.selectById(parentId);
            if (parentProject == null) {
                return ResponseResult.fail(WitmoreErrorCode.PARENT_PROJECT_NOT_EXIST);
            }
            level = parentProject.getProjectLevel() + 1;
        }

        // 解析地址信息
        AddressParserUtils.AddressInfo addressInfo = parseAddress(param.getCurrentAddr(), param.getProjectName());
        // 新增项目
        ProjectDO insertDO = ProjectDO.builder()
                .projectName(param.getProjectName())
                .projectLevel(level)
                .parentId(parentId)
                .orgId(GlobalAccountSession.getUserInfo().getOrgId())
                .currentAddr(param.getCurrentAddr())
                .province(addressInfo == null ? null : addressInfo.getProvince())
                .city(addressInfo == null ? null : addressInfo.getCity())
                .district(addressInfo == null ? null : addressInfo.getDistrict())
                .lng(param.getLng())
                .lat(param.getLat())
                .build();
        projectMapper.insert(insertDO);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> edit(ProjectEditParam param) {
        ProjectDO project = projectMapper.selectOne(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getId, param.getId())
                .eq(ProjectDO::getIsDeleted, 0)
        );
        if (project == null) {
            return ResponseResult.fail(WitmoreErrorCode.PARAM_ERROR);
        }
        // 项目部名称唯一性校验
        ProjectDO projectDO = projectMapper.selectOne(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getProjectName, param.getProjectName())
                .eq(ProjectDO::getIsDeleted, 0)
                .eq(ProjectDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
                .ne(ProjectDO::getId, param.getId())
        );
        if (projectDO != null) {
            return ResponseResult.fail(WitmoreErrorCode.PROJECT_NAME_EXIST);
        }

        // 解析地址信息
        AddressParserUtils.AddressInfo addressInfo = parseAddress(param.getCurrentAddr(), param.getProjectName());

        projectMapper.update(ProjectDO.builder()
                        .projectName(param.getProjectName())
                        .currentAddr(param.getCurrentAddr())
                        .province(addressInfo == null ? null : addressInfo.getProvince())
                        .city(addressInfo == null ? null : addressInfo.getCity())
                        .district(addressInfo == null ? null : addressInfo.getDistrict())
                        .lng(param.getLng())
                        .lat(param.getLat())
                        .build(),
                new LambdaUpdateWrapper<ProjectDO>()
                        .eq(ProjectDO::getId, param.getId())
        );
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> delete(Integer id) {
        ProjectDO project = projectMapper.selectOne(new LambdaQueryWrapper<ProjectDO>()
                .eq(ProjectDO::getId, id)
                .eq(ProjectDO::getIsDeleted, 0)
        );
        if (project == null) {
            return ResponseResult.fail(WitmoreErrorCode.PARAM_ERROR);
        }
        // 项目部下面有业务数据不可删
        // 检查设备表中是否有该项目的数据
        Long deviceCount = deviceMapper.selectCount(new LambdaQueryWrapper<DeviceDO>()
                .eq(DeviceDO::getProjectId, id)
                .eq(DeviceDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
                .eq(DeviceDO::getIsDeleted, 0));

        // 检查摄像头表中是否有该项目的数据
        Long cameraCount = cameraMapper.selectCount(new LambdaQueryWrapper<CameraDO>()
                .eq(CameraDO::getProjectId, id)
                .eq(CameraDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
                .eq(CameraDO::getIsDeleted, 0));

        // 检查管理员关联表中是否有该项目的数据
        List<ProjectBusinessRefDO> adminRefDOS = projectBusinessRefMapper.selectList(new LambdaQueryWrapper<ProjectBusinessRefDO>()
                .eq(ProjectBusinessRefDO::getProjectId, id)
                .eq(ProjectBusinessRefDO::getType, 3) // 只检查管理员类型
                .eq(ProjectBusinessRefDO::getOrgId, GlobalAccountSession.getUserInfo().getOrgId())
        );

        if (deviceCount > 0 || cameraCount > 0 || CollectionUtils.isNotEmpty(adminRefDOS)) {
            return ResponseResult.fail(WitmoreErrorCode.PROJECT_HAVE_BUSINESS_DATA);
        }
        // 逻辑删除
        projectMapper.updateById(ProjectDO.builder().isDeleted(1)
                .id(id)
                .build());
        return ResponseResult.success();
    }

    /**
     * 递归查询子项目id
     *
     * @param parentId 父项目id
     * @param result   结果列表
     */
    private void findChildrenIds(Integer parentId, List<Integer> result) {
        // 查询当前parentId的所有子项目
        List<ProjectDO> children = projectMapper.selectList(new QueryWrapper<ProjectDO>()
                .eq("parent_id", parentId)
                .eq("is_deleted", 0));
        // 遍历子项目，递归查询
        for (ProjectDO child : children) {
            // 添加子项目id
            result.add(child.getId());
            // 递归查询子项目的子项目
            this.findChildrenIds(child.getId(), result);
        }
    }


    /**
     * 构建树形结构
     *
     * @param allProjects 所有项目列表
     * @param orgId       企业 ID（根节点的 parentId）
     * @param needCamera  是否需要摄像头信息
     * @param needCameraPic 是否需要摄像头抓拍图数据
     * @return 树形结构
     */
    private List<ProjectResultVO> buildTree(List<ProjectResultVO> allProjects, int orgId, Boolean needCamera, Boolean needCameraPic) {
        // 用于存储所有项目的映射关系
        Map<Integer, ProjectResultVO> projectMap = new HashMap<>();

        // 初始化所有项目到 Map 中
        for (ProjectResultVO project : allProjects) {
            if (needCamera != null && needCamera) {
                // 查询项目下的摄像头信息
                CameraListParamVO cameraListParamVO = new CameraListParamVO()
                        .setOrgId(orgId)
                        .setProjectIdQuery(project.getId())
                        .setNeedCameraPic(needCameraPic != null ? needCameraPic : false);
                cameraListParamVO.setPage(1);
                cameraListParamVO.setSize(1000);
                ResponsePageResult<CameraResultVO> cameraList = cameraService.getCameraList(cameraListParamVO);
                if (org.apache.commons.lang3.ObjectUtils.isNotEmpty(cameraList) && cameraList.getCode() == WitmoreErrorCode.SUCCESS.getCode()) {
                    project.setCameraResultVOS(cameraList.getRecords());
                }
            }
            projectMap.put(project.getId(), project);
        }

        // 构建树形结构
        List<ProjectResultVO> tree = new ArrayList<>();
        for (ProjectResultVO project : allProjects) {
            if (project.getParentId() == 0) {
                // 根节点
                tree.add(project);
            } else {
                // 子节点
                ProjectResultVO parent = projectMap.get(project.getParentId());
                if (parent != null) {
                    parent.getChildren().add(project);
                }
            }
        }

        return tree;
    }

    @Override
    public ResponseResult<List<ProjectDeviceUsageItemVO>> projectDeviceUsageRank(AccountSession accountSession, ProjectDeviceUsageRankParam param) {
        try {
            // 1. 获取配置的负荷工作时间阈值
            double loadWorkTimeThreshold = businessConfig.getLoadWorkTimeThreshold();

            // 2. 判断查询时间段是否包含今天
            // 根据前端约定：如果包含今天，endDate一定等于今天的日期
            LocalDate today = LocalDate.now();
            LocalDate startDate = LocalDate.parse(param.getStartDate());
            LocalDate endDate = LocalDate.parse(param.getEndDate());
            boolean includeToday = endDate.equals(today);

            // 3. 查询历史数据（不包含今天）
            String historyEndDate = includeToday ? today.minusDays(1).toString() : param.getEndDate();

            // 使用设备级别去重的数据结构
            Map<Integer, Set<Integer>> totalDeviceMap = new HashMap<>();  // 项目ID -> 设备ID集合
            Map<Integer, Set<Integer>> workingDeviceMap = new HashMap<>(); // 项目ID -> 施工设备ID集合
            Map<Integer, String> projectNameMap = new HashMap<>(); // 项目ID -> 项目名称

            // 3.1 查询历史总设备详细信息
            if (!startDate.isAfter(LocalDate.parse(historyEndDate))) {
                List<ProjectDeviceDetailDTO> historyTotalDetails = deviceDailyReportMapper
                        .selectProjectDeviceDetailsByDateRange(
                                accountSession.getOrgId(), param.getStartDate(), historyEndDate);

                // 按项目ID分组，收集设备ID
                for (ProjectDeviceDetailDTO detail : historyTotalDetails) {
                    Integer projectId = detail.getProjectId();
                    totalDeviceMap.computeIfAbsent(projectId, k -> new HashSet<>()).add(detail.getDeviceId());
                    projectNameMap.put(projectId, detail.getProjectName());
                }
            }

            // 3.2 查询历史施工设备详细信息
            if (!startDate.isAfter(LocalDate.parse(historyEndDate))) {
                List<ProjectDeviceDetailDTO> historyWorkingDetails = deviceDailyReportMapper
                        .selectProjectDeviceWorkingDetailsByDateRange(
                                accountSession.getOrgId(), param.getStartDate(), historyEndDate, loadWorkTimeThreshold);

                // 按项目ID分组，收集施工设备ID
                for (ProjectDeviceDetailDTO detail : historyWorkingDetails) {
                    Integer projectId = detail.getProjectId();
                    workingDeviceMap.computeIfAbsent(projectId, k -> new HashSet<>()).add(detail.getDeviceId());
                    projectNameMap.put(projectId, detail.getProjectName());
                }
            }

            // 4. 如果包含今天，补充当天数据
            if (includeToday) {
                // 4.1 当天总设备详细信息
                List<ProjectDeviceDetailDTO> todayTotalDetails = deviceMapper
                        .selectTodayProjectDeviceDetails(accountSession.getOrgId());

                // 4.2 当天施工设备详细信息
                List<ProjectDeviceDetailDTO> todayWorkingDetails = deviceMapper
                        .selectTodayProjectDeviceWorkingDetails(accountSession.getOrgId(), loadWorkTimeThreshold);

                // 4.3 合并当天总设备数据（设备级别去重）
                for (ProjectDeviceDetailDTO detail : todayTotalDetails) {
                    Integer projectId = detail.getProjectId();
                    totalDeviceMap.computeIfAbsent(projectId, k -> new HashSet<>()).add(detail.getDeviceId());
                    projectNameMap.put(projectId, detail.getProjectName());
                }

                // 4.4 合并当天施工设备数据（设备级别去重）
                for (ProjectDeviceDetailDTO detail : todayWorkingDetails) {
                    Integer projectId = detail.getProjectId();
                    workingDeviceMap.computeIfAbsent(projectId, k -> new HashSet<>()).add(detail.getDeviceId());
                    projectNameMap.put(projectId, detail.getProjectName());
                }
            }

            // 5. 构建返回结果（基于去重后的设备集合）
            List<ProjectDeviceUsageItemVO> resultList = new ArrayList<>();
            for (Map.Entry<Integer, Set<Integer>> entry : totalDeviceMap.entrySet()) {
                Integer projectId = entry.getKey();
                Set<Integer> totalDeviceIds = entry.getValue();
                Set<Integer> workingDeviceIds = workingDeviceMap.getOrDefault(projectId, new HashSet<>());

                ProjectDeviceUsageItemVO vo = ProjectDeviceUsageItemVO.builder()
                        .projectId(projectId)
                        .projectName(projectNameMap.get(projectId))
                        .totalDeviceCount(totalDeviceIds.size())  // 去重后的总设备数量
                        .workingDeviceCount(workingDeviceIds.size())  // 去重后的施工设备数量
                        .build();

                resultList.add(vo);
            }

            // 6. 按施工设备数量降序排序
            resultList.sort((a, b) -> Integer.compare(b.getWorkingDeviceCount(), a.getWorkingDeviceCount()));

            return ResponseResult.success(resultList);

        } catch (Exception e) {
            log.error("查询项目设备使用率排名失败", e);
            return ResponseResult.fail(WitmoreErrorCode.SYSTEM_ERROR.getCode(), "查询项目设备使用率排名失败");
        }
    }

    @Override
    public ResponseResult<List<ProjectStartRateVO>> projectStartRateRank(AccountSession accountSession, ProjectDeviceUsageRankParam param) {
        try {
            // 1. 获取配置的负荷工作时间阈值
            double loadWorkTimeThreshold = businessConfig.getLoadWorkTimeThreshold();

            // 2. 判断查询时间段是否包含今天
            LocalDate today = LocalDate.now();
            LocalDate startDate = LocalDate.parse(param.getStartDate());
            LocalDate endDate = LocalDate.parse(param.getEndDate());
            boolean includeToday = endDate.equals(today);

            // 3. 查询历史数据（不包含今天）
            String historyEndDate = includeToday ? today.minusDays(1).toString() : param.getEndDate();

            // 用于存储每个项目部每个设备的施工天数统计
            // Key: projectId, Value: Map<deviceId, ProjectDeviceWorkDaysDTO>
            Map<Integer, Map<Integer, ProjectDeviceWorkDaysDTO>> projectDeviceMap = new HashMap<>();

            // 3.1 查询历史数据
            if (!startDate.isAfter(LocalDate.parse(historyEndDate))) {
                List<ProjectDeviceWorkDaysDTO> historyData = deviceDailyReportMapper
                        .selectProjectDeviceWorkDaysByDateRange(
                                accountSession.getOrgId(), param.getStartDate(), historyEndDate, loadWorkTimeThreshold);

                // 按项目ID和设备ID分组
                for (ProjectDeviceWorkDaysDTO dto : historyData) {
                    Integer projectId = dto.getProjectId();
                    Integer deviceId = dto.getDeviceId();
                    
                    projectDeviceMap.computeIfAbsent(projectId, k -> new HashMap<>()).put(deviceId, dto);
                }
            }

            // 4. 如果包含今天，补充当天数据
            if (includeToday) {
                List<ProjectDeviceWorkDaysDTO> todayData = deviceMapper
                        .selectTodayProjectDeviceWorkDays(accountSession.getOrgId(), loadWorkTimeThreshold);

                // 合并当天数据
                for (ProjectDeviceWorkDaysDTO todayDto : todayData) {
                    Integer projectId = todayDto.getProjectId();
                    Integer deviceId = todayDto.getDeviceId();

                    Map<Integer, ProjectDeviceWorkDaysDTO> deviceMap = projectDeviceMap.computeIfAbsent(projectId, k -> new HashMap<>());
                    
                    if (deviceMap.containsKey(deviceId)) {
                        // 如果历史数据中已有该设备，累加天数
                        ProjectDeviceWorkDaysDTO existingDto = deviceMap.get(deviceId);
                        existingDto.setTotalDays(existingDto.getTotalDays() + todayDto.getTotalDays());
                        existingDto.setWorkingDays(existingDto.getWorkingDays() + todayDto.getWorkingDays());
                    } else {
                        // 如果历史数据中没有该设备，直接添加
                        deviceMap.put(deviceId, todayDto);
                    }
                }
            }

            // 5. 查询所有项目部（包括没有设备的项目部）
            List<ProjectDO> allProjects = projectMapper.selectList(
                    new LambdaQueryWrapper<ProjectDO>()
                            .eq(ProjectDO::getOrgId, accountSession.getOrgId())
                            .eq(ProjectDO::getIsDeleted, 0)
            );

            // 6. 构建返回结果
            List<ProjectStartRateVO> resultList = new ArrayList<>();
            
            for (ProjectDO project : allProjects) {
                Integer projectId = project.getId();
                Map<Integer, ProjectDeviceWorkDaysDTO> deviceMap = projectDeviceMap.get(projectId);

                int totalDeviceCount = 0;
                int workingDeviceCount = 0;
                int totalWorkingDays = 0;
                int totalShouldWorkDays = 0;

                if (deviceMap != null && !deviceMap.isEmpty()) {
                    totalDeviceCount = deviceMap.size();
                    
                    for (ProjectDeviceWorkDaysDTO dto : deviceMap.values()) {
                        // 统计施工设备数（至少施工1天）
                        if (dto.getWorkingDays() > 0) {
                            workingDeviceCount++;
                        }
                        
                        // 累加总实际施工天数和总应施工天数
                        totalWorkingDays += dto.getWorkingDays();
                        totalShouldWorkDays += dto.getTotalDays();
                    }
                }

                // 计算开工率
                String startRate;
                if (totalShouldWorkDays > 0) {
                    double rate = (double) totalWorkingDays / totalShouldWorkDays * 100;
                    startRate = String.format("%.1f%%", rate);
                } else {
                    startRate = "0.0%";
                }

                ProjectStartRateVO vo = ProjectStartRateVO.builder()
                        .projectId(projectId)
                        .projectName(project.getProjectName())
                        .totalDeviceCount(totalDeviceCount)
                        .workingDeviceCount(workingDeviceCount)
                        .startRate(startRate)
                        .build();

                resultList.add(vo);
            }

            // 7. 按开工率降序排序
            resultList.sort((a, b) -> {
                // 提取开工率的数值部分进行比较
                double rateA = Double.parseDouble(a.getStartRate().replace("%", ""));
                double rateB = Double.parseDouble(b.getStartRate().replace("%", ""));
                return Double.compare(rateB, rateA);
            });

            return ResponseResult.success(resultList);

        } catch (Exception e) {
            log.error("查询项目部设备开工率排名失败", e);
            return ResponseResult.fail(WitmoreErrorCode.SYSTEM_ERROR.getCode(), "查询项目部设备开工率排名失败");
        }
    }



}
